Skip to content

fix(channels): reuse local folders, stop git-init prompt on scratch tasks#2793

Merged
raquelmsmith merged 2 commits into
mainfrom
posthog-code/channel-local-folder-reuse
Jun 21, 2026
Merged

fix(channels): reuse local folders, stop git-init prompt on scratch tasks#2793
raquelmsmith merged 2 commits into
mainfrom
posthog-code/channel-local-folder-reuse

Conversation

@raquelmsmith

Copy link
Copy Markdown
Member

What & why

Follow-up to #2735 (generic chat box with lazy repo attach). Fixes two local-mode regressions reported in channel tasks.

1. Reuse local folders instead of cloning from remote

When the agent decided it needed a repo, the channel system prompt sent it straight to list_reposclone_repo, i.e. cloning from remote GitHub even though the user already has the repo checked out locally.

AgentService now fetches the user's previously-used local folders (FoldersService.getFolders) for channel sessions and embeds them in the channel system prompt. Guidance is reordered to:

  1. Reuse a folder already on disk (cd into it).
  2. If unsure / none match → ask the user (via AskUserQuestion) which folder, or for a local path.
  3. Only as a last resort, clone from remote — after confirming with the user.

2. No more spurious "Initialize Git Repository?" dialog

Opening a repo-less channel task popped the native "This folder is not a git repository / initialize?" dialog. Root cause: the synthetic scratch workspace had folderId: "" (falsy), so navigationTaskBinder.ensureWorkspaceForTask's guard missed and it registered the empty scratch dir as a folder (→ FoldersService.addFolder → git-init dialog), plus wrote a bogus workspace row.

Scratch workspaces are now marked with isScratch and short-circuited in the task binder, so they are never registered or git-init'd. The dialog now only fires when a real folder is selected for a coding task.

Changes

  • packages/shared/src/workspace-domain.tsisScratch? on workspaceSchema
  • packages/workspace-server/.../workspace/workspace.tsbuildScratchWorkspace sets isScratch: true
  • packages/ui/.../navigation/taskBinderImpl.ts — short-circuit scratch workspaces
  • packages/workspace-server/.../agent/agent.ts — inject FOLDERS_SERVICE, fetch known local folders in channel mode, embed in the channel prompt

Testing

  • @posthog/workspace-server unit tests (516) pass; added isScratch assertions + foldersService mock
  • ✅ Typecheck clean for touched packages (shared, core, agent, workspace-server); pre-existing unrelated @posthog/ui errors in WebsiteLayout.tsx / InteractiveFileDiff.tsx exist on the base branch
  • ⏳ In-app E2E recommended: channel → analysis prompt (no git dialog, no folder registered) → coding prompt (agent lists local folders / asks before cloning)

Created with PostHog Code

@github-actions

github-actions Bot commented Jun 20, 2026

Copy link
Copy Markdown

React Doctor found no issues in the changed files. 🎉

Reviewed by React Doctor for commit ed8dddb.

@raquelmsmith raquelmsmith marked this pull request as ready for review June 20, 2026 00:08
@greptile-apps

greptile-apps Bot commented Jun 20, 2026

Copy link
Copy Markdown
Contributor
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
packages/workspace-server/src/services/agent/agent.test.ts:179-181
**`localFoldersBlock` branch never exercised in tests**

The mock always resolves to `[]`, so the conditional path in `buildSystemPrompt` that generates the local-folder list (`localFolders.length > 0`) is never reached. The codebase prefers parameterised tests — a case with one or more mock `RegisteredFolder` entries (covering `exists: true`, `exists: false`, and the `remoteUrl` being null/non-null) would verify that the folder list text is correctly assembled and injected, and that folders with `exists: false` are filtered out as intended.

Reviews (1): Last reviewed commit: "fix(channels): reuse local folders, stop..." | Re-trigger Greptile

Comment on lines +179 to +181
foldersService: {
getFolders: vi.fn().mockResolvedValue([]),
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 localFoldersBlock branch never exercised in tests

The mock always resolves to [], so the conditional path in buildSystemPrompt that generates the local-folder list (localFolders.length > 0) is never reached. The codebase prefers parameterised tests — a case with one or more mock RegisteredFolder entries (covering exists: true, exists: false, and the remoteUrl being null/non-null) would verify that the folder list text is correctly assembled and injected, and that folders with exists: false are filtered out as intended.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/workspace-server/src/services/agent/agent.test.ts
Line: 179-181

Comment:
**`localFoldersBlock` branch never exercised in tests**

The mock always resolves to `[]`, so the conditional path in `buildSystemPrompt` that generates the local-folder list (`localFolders.length > 0`) is never reached. The codebase prefers parameterised tests — a case with one or more mock `RegisteredFolder` entries (covering `exists: true`, `exists: false`, and the `remoteUrl` being null/non-null) would verify that the folder list text is correctly assembled and injected, and that folders with `exists: false` are filtered out as intended.

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in ed8dddb. Added a parameterised it.each over buildSystemPrompt in channel mode covering exists: true with a remoteUrl, exists undefined with a null remoteUrl (asserting no empty () suffix), and exists: false (filtered out, block omitted), plus a mixed-list case and the empty-list fallback. The localFolders.length > 0 branch is now exercised.

@raquelmsmith raquelmsmith requested a review from charlesvien June 20, 2026 00:41
@charlesvien charlesvien added the Stamphog This will request an autostamp by stamphog on small changes label Jun 21, 2026
…asks

Follow-up to #2735 (generic chat box with lazy repo attach). Two local-mode
regressions:

1. The channel system prompt sent the agent straight to list_repos/clone_repo,
   cloning from remote even when the user already has the repo checked out
   locally. AgentService now fetches the user's previously-used local folders
   and embeds them in the channel prompt, with guidance to reuse a local match
   (or ask the user for a path) first and only clone from remote as a last
   resort, after confirming.

2. Opening a repo-less channel task popped the native "initialize git?" dialog:
   the synthetic scratch workspace has folderId "" (falsy), so the navigation
   task binder's guard missed and it registered the empty scratch dir as a
   folder. Mark scratch workspaces with isScratch and short-circuit so they are
   never registered or git-init'd. The dialog now only fires when a real folder
   is selected for a coding task.

Generated-By: PostHog Code
Task-Id: d7d5491e-f66a-4848-9620-98006834f3d6
@raquelmsmith raquelmsmith force-pushed the posthog-code/channel-local-folder-reuse branch from 03be99a to 10e1644 Compare June 21, 2026 15:34
The channel system prompt's local-folders block was never covered: the
foldersService mock always resolved to [], so the `localFolders.length > 0`
path in buildSystemPrompt never ran.

Add parameterised cases over buildSystemPrompt in channel mode covering
exists:true with a remoteUrl, exists undefined with a null remoteUrl (no empty
parens), and exists:false (filtered out, block omitted), plus a mixed-list case
and the empty-list fallback. Addresses the review comment on agent.test.ts.

Generated-By: PostHog Code
Task-Id: e61fbdf2-151f-42d2-9c3b-3aaac1bb7959

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No showstoppers. The optional isScratch field is schema-backward-compatible, the early-return in the task binder is correctly scoped, the new DI injection is within the same package with a safe .catch(() => []) guard, and the bot's test-coverage concern was addressed by the new parameterized test suite added in this diff.

@raquelmsmith raquelmsmith merged commit 5bf53ab into main Jun 21, 2026
23 checks passed
@raquelmsmith raquelmsmith deleted the posthog-code/channel-local-folder-reuse branch June 21, 2026 15:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Stamphog This will request an autostamp by stamphog on small changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants